/**
 * @file ffi-api.h
 * @brief SmartAlbum FFI API 契约定义
 * 
 * 这是 SmartAlbum C++ 库与 Dart FFI 之间的稳定契约。
 * 任何对此接口的修改都需要：
 * 1. 语义化版本管理（破坏性变更 = 大版本）
 * 2. 更新 ffigen.yaml 并重新生成绑定
 * 3. 更新 Dart 层封装代码
 * 4. 提供迁移指南
 * 
 * @version 1.0.0
 * @date 2025-10-21
 */

#ifndef SMARTALBUM_FFI_API_H
#define SMARTALBUM_FFI_API_H

#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

// ============================================================================
// 数据结构定义
// ============================================================================

/**
 * @brief 人脸边界框（归一化坐标）
 */
typedef struct {
  float left;    ///< 左边界 [0, 1]
  float right;   ///< 右边界 [0, 1]
  float top;     ///< 上边界 [0, 1]
  float bottom;  ///< 下边界 [0, 1]
} FaceBBoxFFI;

/**
 * @brief 人脸评分
 */
typedef struct {
  FaceBBoxFFI bbox;            ///< 人脸位置
  float confidence;            ///< 检测置信度 [0, 1]
  float sharpness_lapdev;      ///< 清晰度（Laplace 标准差）
  float overexposure_score;    ///< 过曝评分 [0, 1]
  float underexposure_score;   ///< 欠曝评分 [0, 1]
  float position_quality;      ///< 位置质量 [0, 1]
  float size_quality;          ///< 尺寸质量 [0, 1]
  float area_weight;           ///< 面积权重 [0, 1]
} FaceScoreFFI;

/**
 * @brief 单个人脸细节
 */
typedef struct {
  FaceScoreFFI face_score;  ///< 人脸基础评分
  float left_eye_score;     ///< 左眼开合度 [0, 1]
  float right_eye_score;    ///< 右眼开合度 [0, 1]
  float smile_score;        ///< 微笑程度 [0, 1]
} FacialDetailFFI;

/**
 * @brief 图片质量评分详情
 */
typedef struct {
  float sharpness_score;       ///< 整体清晰度 [0, 1]
  float overexposure_score;    ///< 整体过曝 [0, 1]
  float underexposure_score;   ///< 整体欠曝 [0, 1]
  float facial_score;          ///< 人脸综合得分 [0, 1]
  float rotation_suggestion;   ///< 旋转校正建议（度）[-180, 180]
  
  FacialDetailFFI* facial_details;  ///< 人脸细节数组
  int facial_details_count;         ///< 人脸数量
} ScoreDetailFFI;

/**
 * @brief Embedding 特征（用于聚类）
 */
typedef struct {
  int image_id;         ///< 图片 ID
  int64_t timestamp_ms; ///< EXIF 时间戳（毫秒），-1 表示无效
  uint64_t phash;       ///< 64位感知哈希
  
  float* embedding;     ///< Embedding 向量（通常 512 维）
  int embedding_length; ///< 向量长度
} ImageEmbeddingFeaturesFFI;

/**
 * @brief 完整图像特征（输出）
 * 
 * 注意：此结构由 C++ 分配，使用后必须调用 smart_album_free_features() 释放
 */
typedef struct {
  int image_id;                      ///< 图片 ID
  ImageEmbeddingFeaturesFFI embedding;  ///< Embedding 特征
  bool is_valid;                     ///< 是否提取成功
  ScoreDetailFFI score_detail;       ///< 评分详情
} ImageFeaturesFFI;

// ============================================================================
// SDK 生命周期管理
// ============================================================================

/**
 * @brief 初始化 SmartAlbum SDK
 * 
 * 加载所有必需的 NCNN 模型文件。模型文件必须存在于指定目录：
 * - fd.bin, fd.param (人脸检测)
 * - fl.bin, fl.param (人脸关键点)
 * - mobilenetv3_fe.ncnn.bin, mobilenetv3_fe.ncnn.param (特征提取)
 * 
 * @param model_path 模型文件目录的绝对路径
 * @return true 表示初始化成功，false 表示失败
 * 
 * @note 线程安全性：仅支持单 Isolate 调用
 * @note 重复调用：第二次调用会被忽略或返回失败
 * @note 失败处理：调用 smart_album_get_last_error() 获取详细错误
 */
bool smart_album_initialize(const char* model_path);

/**
 * @brief 销毁 SmartAlbum SDK，释放所有资源
 * 
 * 释放所有加载的模型和内存。调用后必须重新 initialize 才能使用。
 * 
 * @note 线程安全性：仅支持单 Isolate 调用
 * @note 异常安全：不会抛出异常
 */
void smart_album_destroy();

/**
 * @brief 检查 SDK 是否已初始化
 * 
 * @return true 表示已初始化并可以使用
 * 
 * @note 线程安全性：仅支持单 Isolate 调用
 */
bool smart_album_is_initialized();

// ============================================================================
// 特征提取
// ============================================================================

/**
 * @brief 从图像提取完整特征
 * 
 * 提取感知哈希、深度学习 Embedding、质量评分、人脸检测等多维特征。
 * 
 * @param image_data 图像数据指针（RGB 或 RGBA 格式）
 * @param width 图像宽度（像素）
 * @param height 图像高度（像素）
 * @param channels 通道数（3 表示 RGB，4 表示 RGBA）
 * @param image_id 图像唯一标识
 * @param timestamp_ms EXIF 时间戳（毫秒），-1 表示无效或未知
 * 
 * @return 图像特征指针，使用后必须调用 smart_album_free_features() 释放
 *         返回 nullptr 表示提取失败，调用 smart_album_get_last_error() 获取详情
 * 
 * @note 前置条件：SDK 必须已初始化（isInitialized() == true）
 * @note 内存管理：image_data 由调用方管理，函数不会修改或释放
 * @note 内存管理：返回的 ImageFeaturesFFI* 由 C++ 分配，Dart 层负责释放
 * @note 线程安全性：仅支持单 Isolate 调用
 * @note 性能：预期 300-500ms（取决于图片大小和设备性能）
 */
ImageFeaturesFFI* smart_album_extract_features(
  const uint8_t* image_data,
  int width,
  int height,
  int channels,
  int image_id,
  int64_t timestamp_ms
);

/**
 * @brief 释放特征结构
 * 
 * 释放由 smart_album_extract_features() 返回的所有内存，包括：
 * - embedding 向量
 * - facial_details 数组
 * - ImageFeaturesFFI 结构本身
 * 
 * @param features 由 smart_album_extract_features() 返回的指针
 * 
 * @note 幂等性：传入 nullptr 是安全的（不会有任何操作）
 * @note 必须调用：每次调用 extract_features 后都必须调用此函数
 * @note 线程安全性：仅支持单 Isolate 调用
 */
void smart_album_free_features(ImageFeaturesFFI* features);

// ============================================================================
// 聚类配置
// ============================================================================

/**
 * @brief 设置聚类阈值
 * 
 * 配置三级匹配策略的阈值：
 * 1. 时间匹配：EXIF 时间戳差值
 * 2. pHash 匹配：汉明距离
 * 3. Embedding 匹配：余弦相似度
 * 
 * @param time_threshold_sec 时间阈值（秒），推荐值: 2.0
 * @param phash_threshold pHash 汉明距离阈值，推荐值: 5
 * @param embedding_threshold Embedding 余弦相似度阈值，推荐值: 0.9
 * 
 * @note 默认值：如果不调用此函数，使用推荐值
 * @note 线程安全性：仅支持单 Isolate 调用
 */
void smart_album_set_clustering_thresholds(
  double time_threshold_sec,
  int phash_threshold,
  float embedding_threshold
);

/**
 * @brief 获取当前聚类阈值
 * 
 * @param[out] time_threshold_sec 时间阈值输出
 * @param[out] phash_threshold pHash 阈值输出
 * @param[out] embedding_threshold Embedding 阈值输出
 * 
 * @note 线程安全性：仅支持单 Isolate 调用
 */
void smart_album_get_clustering_thresholds(
  double* time_threshold_sec,
  int* phash_threshold,
  float* embedding_threshold
);

// ============================================================================
// 错误处理
// ============================================================================

/**
 * @brief 获取最后一次错误信息
 * 
 * 返回最近一次失败操作的详细错误信息。
 * 
 * @return 错误信息字符串（C 字符串，静态内存，不需要释放）
 *         如果没有错误，返回空字符串
 * 
 * @note 线程本地：每个线程/Isolate 有独立的错误状态
 * @note 有效期：下次 API 调用前有效
 */
const char* smart_album_get_last_error();

// ============================================================================
// 版本信息
// ============================================================================

/**
 * @brief 获取 SDK 版本
 * 
 * @return 版本字符串，格式: "major.minor.patch"
 */
const char* smart_album_get_version();

// ============================================================================
// 聚类功能（可选实现）
// ============================================================================

/**
 * @brief 对单个特征进行聚类
 * 
 * 注意：此函数接口较复杂，建议在 Dart 层实现聚类逻辑。
 * 此处仅作为契约预留，可以在后续版本实现。
 * 
 * @param groups 现有聚类组（展平的二维数组）
 * @param group_sizes 每个组的特征数量
 * @param group_count 组的数量
 * @param new_feature 新特征
 * 
 * @return 分配到的组索引，-1 表示创建新组
 * 
 * @note MVP 版本：可以不实现，返回 -1（由 Dart 层实现聚类）
 */
int smart_album_cluster_feature(
  const ImageEmbeddingFeaturesFFI* groups,
  const int* group_sizes,
  int group_count,
  const ImageEmbeddingFeaturesFFI* new_feature
);

#ifdef __cplusplus
}
#endif

#endif  // SMARTALBUM_FFI_API_H

/**
 * API 契约版本历史:
 * 
 * v1.0.0 (2025-10-21):
 * - 初始版本
 * - 定义核心数据结构
 * - 定义生命周期管理 API
 * - 定义特征提取 API
 * - 定义聚类配置 API
 * - 聚类功能预留，MVP 不实现
 * 
 * 破坏性变更政策:
 * - 添加新字段: 次版本更新（向后兼容）
 * - 修改字段类型: 大版本更新（破坏性变更）
 * - 删除字段/函数: 大版本更新（破坏性变更）
 * - 修改函数签名: 大版本更新（破坏性变更）
 */

